package org.example.oop.reflection;


import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * org.example.oop.reflection
 *
 * @author moLei
 * @description
 * @date 2025/7/11
 */
public class ReflectionDemo extends Father {


    /**
     * static 的代码是按照先后顺序进行执行的
     */

    static {
        a = 100;
    }

    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException {

        // 反射的代码测试示例
        testReflection();


        // 验证反射和关闭安全检查之间的效率提升
        testCloseAccessible();
    }

    private void setA(int a) {
        this.a = a;
    }

    static {
        a = 200;
    }

    static int a = 10;

    private int b;

    public int c;

    private ReflectionDemo() {

    }

    public ReflectionDemo(int a) {

    }

    /**
     * 测试反射代码
     */
    public static void testReflection() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, ClassNotFoundException {
        Class<ReflectionDemo> reflectionDemoClass = ReflectionDemo.class;
        ReflectionDemo reflectionDemo = reflectionDemoClass.newInstance();

        Class aClass = reflectionDemo.getClass();

        Class aClass1 = Class.forName("org.example.oop.reflection.ReflectionDemo");

        // 获取父类的Class对象
        Class superclass = aClass1.getSuperclass();

        aClass.getMethods();
        System.out.println(a);

        new Son();
        new Son();

        new String();

        System.out.println("getDeclaredMethods===========================================");
        // 获取类的所有方法包含private，不包含父类的
        Method[] declaredMethods = aClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
        System.out.println("getMethods==============================================");
        // 获取类的所有public方法，包括父类的
        declaredMethods = aClass.getMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
        // 通过反射调用方法
        Method setA = aClass.getDeclaredMethod("setA", int.class);
        // 关闭安全检查，不然无法操作私有属性，设置私有方法可操作，提高反射的效率
        setA.setAccessible(true);


        // 获取类的所有属性，不包含父类的
        System.out.println("getDeclaredFields=============================================");
        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        // 获取类的public属性，包含父类的
        System.out.println("getFields===============================================");
        declaredFields = aClass.getFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }

        // 获取类的构造方法，包含私有的
        System.out.println("getDeclaredConstructors===========================================");
        Constructor[] declaredConstructors = aClass.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
        // 获取类的public构造方法
        System.out.println("getConstructors===============================================");
        declaredConstructors = aClass.getConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }

        // 获取有参构造器
        Constructor declaredConstructor = aClass.getDeclaredConstructor(int.class);
        Object o = declaredConstructor.newInstance(3);
    }


    /**
     * 测试关闭安全检查提升的时间
     */
    public static void testCloseAccessible() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        long begin = System.currentTimeMillis();
        // 通过反射获取方法
        Class<?> aClass = Class.forName("org.example.oop.reflection.Son");
        Son son = (Son) aClass.newInstance();
        Method getName = aClass.getMethod("getName", null);
        for (long i = 0; i < 100000000000l; i++) {
            getName.invoke(son, null);
        }
        System.out.println("通过反射获取方法执行10亿次的时间：" + (System.currentTimeMillis() - begin));

        // 通过正常方法执行的时间
        Son son1 = new Son();
        begin = System.currentTimeMillis();
        for (long i = 0; i < 100000000000l; i++) {
            son1.getName();
        }
        System.out.println("通过正常创建对象调用方法的时间：" + (System.currentTimeMillis() - begin));

        // 关闭安全检查调用方法
        getName.setAccessible(true);
        begin = System.currentTimeMillis();
        for (long i = 0; i < 100000000000l; i++) {
            son.getName();
        }
        System.out.println("通过反射关闭安全检查嗲用方法的时间" + (System.currentTimeMillis() - begin));
    }
}

class Father {

    private Father(int b) {

    }

    public Father() {

    }
    public int d;
    static {
        System.out.println("father");
    }
}

class Son extends Father {
    static {
        System.out.println("son");
    }

    public void getName() {

    }
}
